package com.ruoyi.pos.domain.transaction;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;

import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.util.Date;

/**
 * POS销售支付信息实体类
 * 
 * 用于记录POS系统中的销售支付详情，支持多种支付方式
 * 包含完整的银行交易信息、第三方支付信息和原始报文数据
 * 支持混合支付，一笔销售可以有多种支付方式
 * 
 * @author POS System
 * @since 1.0.0
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class PosSalePay extends BaseEntity {
    
    private static final long serialVersionUID = 1L;

    /**
     * 支付ID（主键）
     */
    private Long paymentId;

    /**
     * 销售ID
     * 
     * 关联pos_sale表
     */
    @Excel(name = "销售ID")
    @NotNull(message = "销售ID不能为空")
    private Long transactionId;

    /**
     * 销售流水号
     */
    @Excel(name = "销售流水号")
    @NotBlank(message = "销售流水号不能为空")
    @Size(max = 32, message = "销售流水号长度不能超过32个字符")
    private String transactionNo;

    /**
     * 支付流水号
     * 
     * 全局唯一，用于标识一笔支付
     */
    @Excel(name = "支付流水号")
    @NotBlank(message = "支付流水号不能为空")
    @Size(max = 32, message = "支付流水号长度不能超过32个字符")
    private String paymentNo;

    /**
     * 支付方式
     * 
     * CASH-现金 CARD-银行卡 ALIPAY-支付宝 WECHAT-微信支付 POINTS-积分支付
     */
    @Excel(name = "支付方式")
    @NotBlank(message = "支付方式不能为空")
    @Size(max = 20, message = "支付方式长度不能超过20个字符")
    private String paymentType;

    /**
     * 支付方式名称
     */
    @Excel(name = "支付方式名称")
    @Size(max = 50, message = "支付方式名称长度不能超过50个字符")
    private String paymentName;

    /**
     * 支付金额
     */
    @Excel(name = "支付金额")
    @NotNull(message = "支付金额不能为空")
    @DecimalMin(value = "0.00", message = "支付金额不能小于0")
    private BigDecimal paymentAmount;

    /**
     * 实收金额
     * 
     * 实际收到的金额，可能包含手续费
     */
    @Excel(name = "实收金额")
    @DecimalMin(value = "0.00", message = "实收金额不能小于0")
    private BigDecimal receivedAmount;

    /**
     * 找零金额
     */
    @Excel(name = "找零金额")
    @DecimalMin(value = "0.00", message = "找零金额不能小于0")
    private BigDecimal changeAmount;

    /**
     * 支付状态
     * 
     * 1-成功 2-失败 3-退款
     */
    @Excel(name = "支付状态", readConverterExp = "1=成功,2=失败,3=退款")
    @Size(max = 1, message = "支付状态长度不能超过1个字符")
    private String paymentStatus;

    /**
     * 第三方流水号
     * 
     * 支付宝、微信等第三方平台的流水号
     */
    @Excel(name = "第三方流水号")
    @Size(max = 64, message = "第三方流水号长度不能超过64个字符")
    private String thirdPartyNo;

    /**
     * 第三方响应
     * 
     * 第三方平台的响应信息
     */
    @Excel(name = "第三方响应")
    private String thirdPartyResponse;

    /**
     * 银行卡号（脱敏）
     * 
     * 银行卡号，已脱敏处理
     */
    @Excel(name = "银行卡号")
    @Size(max = 32, message = "银行卡号长度不能超过32个字符")
    private String bankCardNo;

    /**
     * 银行名称
     */
    @Excel(name = "银行名称")
    @Size(max = 50, message = "银行名称长度不能超过50个字符")
    private String bankName;

    /**
     * 卡类型
     * 
     * DEBIT-借记卡 CREDIT-信用卡
     */
    @Excel(name = "卡类型", readConverterExp = "DEBIT=借记卡,CREDIT=信用卡")
    @Size(max = 20, message = "卡类型长度不能超过20个字符")
    private String cardType;

    /**
     * 授权码
     * 
     * 银行返回的授权码
     */
    @Excel(name = "授权码")
    @Size(max = 32, message = "授权码长度不能超过32个字符")
    private String authCode;

    /**
     * 终端号
     */
    @Excel(name = "终端号")
    @Size(max = 32, message = "终端号长度不能超过32个字符")
    private String terminalNo;

    /**
     * 商户号
     */
    @Excel(name = "商户号")
    @Size(max = 32, message = "商户号长度不能超过32个字符")
    private String merchantNo;

    // ==================== 原始交易报文 ====================

    /**
     * 原始请求报文
     * 
     * 发送给银行或第三方的原始请求报文
     */
    @Excel(name = "原始请求报文")
    private String originalRequest;

    /**
     * 原始响应报文
     * 
     * 银行或第三方返回的原始响应报文
     */
    @Excel(name = "原始响应报文")
    private String originalResponse;

    /**
     * 银行请求报文
     * 
     * 发送给银行的请求报文
     */
    @Excel(name = "银行请求报文")
    private String bankRequest;

    /**
     * 银行响应报文
     * 
     * 银行返回的响应报文
     */
    @Excel(name = "银行响应报文")
    private String bankResponse;

    /**
     * 银行错误码
     */
    @Excel(name = "银行错误码")
    @Size(max = 20, message = "银行错误码长度不能超过20个字符")
    private String bankErrorCode;

    /**
     * 银行错误信息
     */
    @Excel(name = "银行错误信息")
    @Size(max = 500, message = "银行错误信息长度不能超过500个字符")
    private String bankErrorMessage;

    /**
     * 银行批次号
     */
    @Excel(name = "银行批次号")
    @Size(max = 32, message = "银行批次号长度不能超过32个字符")
    private String bankBatchNo;

    /**
     * 银行参考号
     */
    @Excel(name = "银行参考号")
    @Size(max = 32, message = "银行参考号长度不能超过32个字符")
    private String bankReferenceNo;

    /**
     * 银行流水号
     */
    @Excel(name = "银行流水号")
    @Size(max = 32, message = "银行流水号长度不能超过32个字符")
    private String bankTraceNo;

    /**
     * POS响应码
     */
    @Excel(name = "POS响应码")
    @Size(max = 10, message = "POS响应码长度不能超过10个字符")
    private String posResponseCode;

    /**
     * POS响应信息
     */
    @Excel(name = "POS响应信息")
    @Size(max = 200, message = "POS响应信息长度不能超过200个字符")
    private String posResponseMessage;

    // ==================== 时间相关 ====================

    /**
     * 支付时间
     */
    @Excel(name = "支付时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @NotNull(message = "支付时间不能为空")
    private Date paymentTime;

    /**
     * 银行交易时间
     */
    @Excel(name = "银行交易时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date bankTradeTime;

    /**
     * 退款时间
     */
    @Excel(name = "退款时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date refundTime;

    /**
     * 退款金额
     */
    @Excel(name = "退款金额")
    @DecimalMin(value = "0.00", message = "退款金额不能小于0")
    private BigDecimal refundAmount;

    /**
     * 退款原因
     */
    @Excel(name = "退款原因")
    @Size(max = 200, message = "退款原因长度不能超过200个字符")
    private String refundReason;

    /**
     * 操作员ID
     */
    @Excel(name = "操作员ID")
    private Long operatorId;

    /**
     * 操作员姓名
     */
    @Excel(name = "操作员姓名")
    @Size(max = 50, message = "操作员姓名长度不能超过50个字符")
    private String operatorName;

    /**
     * 备注
     */
    @Excel(name = "备注")
    @Size(max = 200, message = "备注长度不能超过200个字符")
    private String remark;

    /**
     * 创建时间
     */
    @Excel(name = "创建时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    /**
     * 更新时间
     */
    @Excel(name = "更新时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;

    // ==================== 扩展字段 ====================

    /**
     * 支付方式显示名称（非数据库字段）
     */
    @Excel(name = "支付方式")
    private String paymentTypeDisplay;

    /**
     * 支付状态显示名称（非数据库字段）
     */
    @Excel(name = "支付状态")
    private String paymentStatusDisplay;

    /**
     * 卡类型显示名称（非数据库字段）
     */
    @Excel(name = "卡类型")
    private String cardTypeDisplay;

    // ==================== 业务方法 ====================

    /**
     * 获取支付方式显示名称
     */
    public String getPaymentTypeDisplay() {
        if (paymentType == null) {
            return "未知";
        }
        switch (paymentType) {
            case "CASH": return "现金";
            case "CARD": return "银行卡";
            case "ALIPAY": return "支付宝";
            case "WECHAT": return "微信支付";
            case "POINTS": return "积分支付";
            default: return paymentName != null ? paymentName : "未知";
        }
    }

    /**
     * 获取支付状态显示名称
     */
    public String getPaymentStatusDisplay() {
        if (paymentStatus == null) {
            return "未知";
        }
        switch (paymentStatus) {
            case "1": return "成功";
            case "2": return "失败";
            case "3": return "退款";
            default: return "未知";
        }
    }

    /**
     * 获取卡类型显示名称
     */
    public String getCardTypeDisplay() {
        if (cardType == null) {
            return "未知";
        }
        switch (cardType) {
            case "DEBIT": return "借记卡";
            case "CREDIT": return "信用卡";
            default: return "未知";
        }
    }

    /**
     * 判断支付是否成功
     */
    public boolean isSuccess() {
        return "1".equals(paymentStatus);
    }

    /**
     * 判断是否为现金支付
     */
    public boolean isCashPayment() {
        return "CASH".equals(paymentType);
    }

    /**
     * 判断是否为银行卡支付
     */
    public boolean isCardPayment() {
        return "CARD".equals(paymentType);
    }

    /**
     * 判断是否为电子支付
     */
    public boolean isElectronicPayment() {
        return "ALIPAY".equals(paymentType) || "WECHAT".equals(paymentType);
    }

    /**
     * 判断是否为积分支付
     */
    public boolean isPointsPayment() {
        return "POINTS".equals(paymentType);
    }

    /**
     * 判断是否需要找零
     */
    public boolean needChange() {
        return isCashPayment() && changeAmount != null && changeAmount.compareTo(BigDecimal.ZERO) > 0;
    }

    /**
     * 计算手续费
     * 
     * @return 手续费金额
     */
    public BigDecimal calculateFee() {
        if (paymentAmount == null || receivedAmount == null) {
            return BigDecimal.ZERO;
        }
        
        BigDecimal fee = receivedAmount.subtract(paymentAmount);
        return fee.compareTo(BigDecimal.ZERO) > 0 ? fee : BigDecimal.ZERO;
    }

    /**
     * 获取支付金额显示
     * 
     * @return 格式化的支付金额字符串
     */
    public String getPaymentAmountDisplay() {
        if (paymentAmount == null) {
            return "¥0.00";
        }
        return "¥" + paymentAmount.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 获取找零金额显示
     * 
     * @return 格式化的找零金额字符串
     */
    public String getChangeAmountDisplay() {
        if (changeAmount == null || changeAmount.compareTo(BigDecimal.ZERO) == 0) {
            return "¥0.00";
        }
        return "¥" + changeAmount.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 验证支付数据完整性
     * 
     * @return 是否完整
     */
    public boolean isDataComplete() {
        return transactionId != null &&
               transactionNo != null && !transactionNo.trim().isEmpty() &&
               paymentNo != null && !paymentNo.trim().isEmpty() &&
               paymentType != null && !paymentType.trim().isEmpty() &&
               paymentAmount != null && paymentAmount.compareTo(BigDecimal.ZERO) > 0 &&
               paymentTime != null;
    }

    /**
     * 获取支付摘要信息
     * 
     * @return 支付摘要
     */
    public String getSummary() {
        StringBuilder summary = new StringBuilder();
        summary.append("支付号: ").append(paymentNo);
        summary.append(", 方式: ").append(getPaymentTypeDisplay());
        summary.append(", 金额: ").append(getPaymentAmountDisplay());
        summary.append(", 状态: ").append(getPaymentStatusDisplay());
        summary.append(", 时间: ").append(paymentTime != null ? 
            new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(paymentTime) : "未知");
        
        return summary.toString();
    }

    // ==================== 备用扩展字段 ====================
    
    /**
     * 备用字段1
     */
    private String reserved1;

    /**
     * 备用字段2
     */
    private String reserved2;

    /**
     * 备用字段3
     */
    private String reserved3;

    /**
     * 备用字段4
     */
    private String reserved4;

    /**
     * 备用字段5
     */
    private String reserved5;
}
